package com.easygoods.service;

import com.bestvike.linq.Linq;
import com.bestvike.stone.core.lang.BeanUtils;
import com.bestvike.stone.core.lang.RandomUtils;
import com.bestvike.stone.core.util.area.AreaUtils;
import com.bestvike.stone.core.util.area.City;
import com.bestvike.stone.core.util.area.County;
import com.bestvike.stone.core.util.area.Province;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.service.BaseService;
import com.easygoods.dao.MemberAddressDao;
import com.easygoods.dao.MemberInfoDao;
import com.easygoods.entity.MemberAddress;
import com.easygoods.entity.MemberInfo;
import com.easygoods.enums.AddressType;
import com.easygoods.enums.YNEnum;
import com.easygoods.request.AddressAddRequest;
import com.easygoods.request.AddressDeleteRequest;
import com.easygoods.request.AddressModifyRequest;
import com.easygoods.request.AddressSetDefaultRequest;
import com.easygoods.response.AddressCodeResponse;
import com.easygoods.response.AddressListResponse;
import com.easygoods.response.AddressListResponseItem;
import com.easygoods.shiro.auth.UserAuth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.util.List;
import java.util.Objects;

/**
 * @author zhq
 * @date 2019/1/2 15:46
 */
@Service
public class AddressService extends BaseService {
    @Autowired
    private MemberAddressDao memberAddressDao;
    @Autowired
    private MemberService memberService;
    @Autowired
    private MemberInfoDao memberInfoDao;

    //根据前端传来的memberAddressRequest 设置 memberAddress
    private void setAddressProperties(MemberAddress memberAddress, AddressAddRequest request) {
        memberAddress.setProvinceId(request.getProvinceId());
        memberAddress.setProvinceName(request.getProvinceName());
        memberAddress.setCityId(request.getCityId());
        memberAddress.setCityName(request.getCityName());
        memberAddress.setCountyId(request.getCountyId());
        memberAddress.setCountyName(request.getCountyName());
        memberAddress.setTownId(request.getTownId());
        memberAddress.setTownName(request.getTownName());
        memberAddress.setDetailedAddress(request.getDetailedAddress());
        memberAddress.setContactPerson(request.getContactPerson());
        memberAddress.setContactMobile(request.getContactMobile());
        memberAddress.setAddressType(request.getAddressType().name());
        memberAddress.setAddressTag(request.getAddressTag());
    }

    //根据id,memberId,地址类型查询地址记录
    public MemberAddress getAddress(String id, String memberId, AddressType addressType) {
        Example addressExample = new Example(MemberAddress.class);
        addressExample.createCriteria().andEqualTo(MemberAddress.ID, id).andEqualTo(MemberAddress.MEMBER_ID, memberId).andEqualTo(MemberAddress.ADDRESS_TYPE, addressType.name());
        MemberAddress address = this.memberAddressDao.selectOneByExample(addressExample);
        if (address == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的操作, 请刷新");
        return address;
    }

    //获取省份列表
    @SuppressWarnings("unused")
    public List<AddressCodeResponse> getProvinceList() {
        return Linq.asEnumerable(AreaUtils.getProvinceCollection())
                .select(p -> new AddressCodeResponse(p.getCode(), p.getName())).toList();
    }

    //获取城市列表
    @SuppressWarnings("unused")
    public List<AddressCodeResponse> getCityList(String provinceCode) {
        Province province = AreaUtils.getProvince(provinceCode);
        if (province == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的省份代码");

        return Linq.asEnumerable(province.getCityCollection())
                .select(p -> new AddressCodeResponse(p.getCode(), p.getName())).toList();
    }

    //获取地区列表
    @SuppressWarnings("unused")
    public List<AddressCodeResponse> getCountyList(String cityCode) {
        City city = AreaUtils.getCity(cityCode);
        if (city == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的城市代码");

        return Linq.asEnumerable(city.getCountyCollection())
                .select(p -> new AddressCodeResponse(p.getCode(), p.getName())).toList();
    }

    //获取街道列表
    @SuppressWarnings("unused")
    public List<AddressCodeResponse> getTownList(String countyCode) {
        County county = AreaUtils.getCounty(countyCode);
        if (county == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的地区代码");

        return Linq.asEnumerable(county.getTownCollection())
                .select(p -> new AddressCodeResponse(p.getCode(), p.getName())).toList();
    }

    //新增收货地址、寄件地址，根据地址类型来区分
    public void addAddress(AddressAddRequest request) {
        final UserAuth userAuth = this.getAuth();
        String memberId = userAuth.getMemberId();
        MemberAddress memberAddress = new MemberAddress();
        memberAddress.setId(RandomUtils.randomUUID());
        memberAddress.setMemberId(memberId);
        this.setAddressProperties(memberAddress, request);
        memberAddress.beforeInsert();
        int memberAddressNum = this.memberAddressDao.insert(memberAddress);
        if (memberAddressNum != 1) {
            this.log.error("新增收货或寄件地址失败");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "新增地址失败");
        }
        //默认地址
        if (request.getDefaultAddress() != YNEnum.Y)
            return;
        MemberInfo memberInfoUpdate = new MemberInfo();
        memberInfoUpdate.setId(memberId);
        if (request.getAddressType() == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的地址类型");
        switch (request.getAddressType()) {
            case Send:
                memberInfoUpdate.setDefaultSendAddress(memberAddress.getId());
                break;
            case Receive:
                memberInfoUpdate.setDefaultReceiveAddress(memberAddress.getId());
                break;
            default:
                throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的地址类型");
        }
        this.memberInfoDao.updateByPrimaryKeySelective(memberInfoUpdate);
    }

    //根据主键id删除收货地址、寄件地址
    public void removeAddress(AddressDeleteRequest request) {
        //验证
        final UserAuth userAuth = this.getAuth();
        this.getAddress(request.getId(), userAuth.getMemberId(), request.getAddressType());
        //删除
        int deleteNum = this.memberAddressDao.deleteByPrimaryKey(request.getId());
        if (deleteNum != 1) {
            this.log.error("删除地址失败");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "删除地址失败");
        }
    }

    //修改地址内容
    public void modifyAddress(AddressModifyRequest request) {
        //验证
        final UserAuth userAuth = this.getAuth();
        this.getAddress(request.getId(), userAuth.getMemberId(), request.getAddressType());
        //修改
        MemberAddress memberAddress = new MemberAddress();
        memberAddress.setId(request.getId());
        this.setAddressProperties(memberAddress, request);
        memberAddress.beforeUpdate();
        int updateNum = this.memberAddressDao.updateByPrimaryKeySelective(memberAddress);
        if (updateNum != 1) {
            this.log.error("更新收货、寄件地址失败");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "更新收货、寄件地址失败");
        }
        if (request.getDefaultAddress() == YNEnum.Y) {
            AddressSetDefaultRequest addressSetDefaultRequest = new AddressSetDefaultRequest();
            addressSetDefaultRequest.setId(request.getId());
            addressSetDefaultRequest.setAddressType(request.getAddressType());
            this.setAsDefaultAddress(addressSetDefaultRequest);
        }
    }

    //设为默认地址
    public void setAsDefaultAddress(AddressSetDefaultRequest request) {
        //验证
        final UserAuth userAuth = this.getAuth();
        this.getAddress(request.getId(), userAuth.getMemberId(), request.getAddressType());
        //更新
        MemberInfo memberInfo = new MemberInfo();
        memberInfo.setId(userAuth.getMemberId());
        if (request.getAddressType() == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "地址类型无效");
        switch (request.getAddressType()) {
            case Send:
                memberInfo.setDefaultSendAddress(request.getId());
                break;
            case Receive:
                memberInfo.setDefaultReceiveAddress(request.getId());
                break;
            default:
                throw new BusinessException(ErrorCode.ERROR_SERVER, "地址类型无效");
        }
        memberInfo.beforeUpdate();
        int updateSendNum = this.memberInfoDao.updateByPrimaryKeySelective(memberInfo);
        if (updateSendNum != 1) {
            this.log.error("设为默认地址失败");
            throw new BusinessException(ErrorCode.ERROR_SERVER, "设为默认地址失败");
        }
    }

    //根据地址类型查询地址列表
    public AddressListResponse getAddressList(AddressType addressType) {
        MemberInfo memberInfo = this.memberService.getMemberInfo();
        //查询地址
        Example addressExample = new Example(MemberAddress.class);
        addressExample.createCriteria().andEqualTo(MemberAddress.MEMBER_ID, memberInfo.getId()).andEqualTo(MemberAddress.ADDRESS_TYPE, addressType);
        List<MemberAddress> memberAddressList = this.memberAddressDao.selectByExample(addressExample);
        //转换
        List<AddressListResponseItem> addressItems = BeanUtils.toList(memberAddressList, AddressListResponseItem.class);
        String defaultAddressId = addressType == AddressType.Send
                ? memberInfo.getDefaultSendAddress()
                : memberInfo.getDefaultReceiveAddress();
        for (AddressListResponseItem addressItem : addressItems) {
            boolean isDefault = Objects.equals(addressItem.getId(), defaultAddressId);
            addressItem.setDefaultAddress(YNEnum.parse(isDefault));
        }
        //返回
        AddressListResponse response = new AddressListResponse();
        response.setDefaultAddress(defaultAddressId);
        response.setAddresses(addressItems);
        return response;
    }
}
